Technical Q&AQTMTB 57 - How do I decompress individual frames into an offscreen? (24-April-2000)Q: How can you scale and decompress individual frames of a video track into an offscreen RGB buffer so the pixels can be further manipulated?
A: The code snippets below show how a single frame can be drawn into a
The full sample application called // Globals --------------------------------------------------------------------- GWorldPtr gSrcGWorld = NULL; Movie gMovie = NULL; TimeValue gMovieTime = 0; // set current time value to beginning of the movie UInt32 gFrameCount = -1; UInt32 gFrameNumber = 0; // CountThemFrames ------------------------------------------------------------- // Count the number of video "frames" in the movie by stepping through // all of the video "interesting times", or in other words, the places where the // movie displays a new video sample. The time between these interesting times is not // necessarily constant. //------------------------------------------------------------------------------ void CountThemFrames( void ) { OSType whichMediaType = VIDEO_TYPE; short flags = nextTimeMediaSample + nextTimeEdgeOK; TimeValue duration; TimeValue theTime = 0; while (theTime >= 0) { gFrameCount++; GetMovieNextInterestingTime(gMovie, flags, 1, &whichMediaType, theTime, 0, &theTime, &duration); // after the first interesting time, don't include the time we // are currently at. flags = nextTimeMediaSample; } // while } // MakeGWorld ------------------------------------------------------------------ // Get the bounding rectangle of the movie and create a 32-bit gworld // with those dimensions. // This GWorld will be used for rendering movie frames into. //------------------------------------------------------------------------------ void MakeGWorld( void ) { Rect srcRect; Rect portRect; OSErr err = noErr; // get the movies dimensions GetMovieBox(gMovie,&srcRect); err = NewGWorld(&gSrcGWorld, k32ARGBPixelFormat, &srcRect, NULL, NULL, 0); BailError(err); // make sure to lock the PixMap LockPixels(GetGWorldPixMap(gSrcGWorld)); // erase SetGWorld(gSrcGWorld,NULL); GetPortBounds(gSrcGWorld, &portRect); EraseRect(&portRect); // *** tell the movie to draw into the GWorld *** SetMovieGWorld(gMovie,gSrcGWorld,GetGWorldDevice(gSrcGWorld)); bail: return; } // NextFrame ------------------------------------------------------------------- // Get the next frame of the movie, set the movie time for that frame, // then task the movie which will draw the frame to the GWorld. // Modify the movie matrix so the next frame will be rotated just for fun, and // finally, draw the frame number on top of the image and inval the window rect. //------------------------------------------------------------------------------ void NextFrame( void ) { if ( gFrameNumber < gFrameCount ) { TimeValue duration; // get the next frame of the source movie short flags = nextTimeMediaSample; OSType whichMediaType = VIDEO_TYPE; // if this is the first frame, include the frame we are currently on if (gFrameNumber == 0) flags |= nextTimeEdgeOK; // skip to the next interesting time and get the duration for that frame GetMovieNextInterestingTime(gMovie, flags, 1, &whichMediaType, gMovieTime, 0, &gMovieTime, &duration); // set the time for the frame and give time to the movie toolbox SetMovieTimeValue(gMovie,gMovieTime); // *** tasking the movie does the actual draw *** MoviesTask(gMovie,0); } //------------------------------------------------------------------------------ // You now have pixels you can play with in the GWorld! //------------------------------------------------------------------------------ } -- Edward Agabeg Worldwide Developer Technical Support Technical Q&A | Contents Previous Question To contact us, please use the Contact Us page. |